

package cn.shengchao.controler.course;

import cn.hutool.core.util.StrUtil;
import cn.shengchao.controler.ai.AiController;
import cn.shengchao.examstar.ai.domain.repository.IAiChatFreeSunRepository;
import cn.shengchao.examstar.ai.infrastructure.external.ai.agent.KnowledgeExtractionAgent;
import cn.shengchao.examstar.ai.infrastructure.external.ai.memory.AiChatMemoryService;
import cn.shengchao.examstar.ai.infrastructure.external.ai.prompt.CommentsPrompt;
import cn.shengchao.examstar.ai.infrastructure.external.ai.util.AiClientUtil;
import cn.shengchao.examstar.ai.infrastructure.external.ai.util.entity.AiVideoResult;
import cn.shengchao.examstar.ai.infrastructure.external.ai.util.entity.Questions;
import cn.shengchao.examstar.distribute.infrastrure.po.DistributeNodeInfo;
import cn.shengchao.examstar.distribute.infrastrure.service.DistributeNodeInfoService;
import cn.shengchao.examstar.rpc.distribute.enums.DistributeSaleRoleEnum;
import cn.shengchao.util.helper.LoginHelper;
import cn.shengchao.examstar.me.course.domain.MyCourse;
import cn.shengchao.examstar.me.course.ohs.local.appervices.MyCourseAppService;
import cn.shengchao.examstart.medialibrary.ohs.local.appservice.VideoService;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import top.continew.starter.cache.redisson.util.RedisUtils;
import top.continew.starter.core.validation.CheckUtils;
import top.continew.starter.log.annotation.Log;

import java.time.Duration;
import java.util.List;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;

@RestController
@Slf4j
@CrossOrigin("${project.cross-origin}")
@RequestMapping("/api/${project.version}/myCourse/ai")
public class CourseAiController {
    @Autowired
    private AiClientUtil aiClientUtil;
    @Autowired
    private VideoService videoService;

    @Autowired
    private MyCourseAppService myCourseAppService;

    @Autowired
    private DistributeNodeInfoService distributeNodeInfoService;

    @Autowired
    private KnowledgeExtractionAgent knowledgeExtractionAgent;

    @Autowired
    private AiChatMemoryService aiChatMemoryService;

    @Autowired
    private AiController aiController;

    @Autowired
    private IAiChatFreeSunRepository iAiChatFreeSunRepository;

    @Log(ignore = true)
    @Operation(hidden = true)
    @GetMapping("/question")
    public Questions question(@RequestParam Long courseId,
                              @RequestParam long courseNodeId, @RequestParam(required = false) String videoUrl) throws Exception {
        String key = "ai_course_question_" + courseId + "_" + courseNodeId;
        Questions question = RedisUtils.get(key);
        if (question != null) {
            return question;
        }
        //获取视频内容
        AiVideoResult aiVideoResult = this.getFileTaskResult(courseId, courseNodeId, videoUrl);
        if (aiVideoResult.getBriefly() == null) {
            return new Questions();
        }
        //提取视频内容生成题目
        question = knowledgeExtractionAgent.extractKnowledge(aiVideoResult.getBriefly());
        RedisUtils.set(key, question, Duration.ofDays(1));
        return question;
    }

    @Log(ignore = true)
    @Operation(hidden = true)
    @GetMapping(value = "/generateStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamChat(@RequestParam String question,
                                   @RequestParam String message,
                                   @RequestParam String sessionId,
                                   @RequestParam Long courseId,
                                   @RequestParam Long courseNodeId, @RequestParam(required = false) String videoUrl
    ) throws Exception {
        CheckUtils.throwIf(aiController.getFreeSum().getValue() <= 0, "免费次数不足");
        iAiChatFreeSunRepository.doAi(LoginHelper.getUserId(), 1L);
        ChatClient client = aiClientUtil.getChatClient();
        //定义系统角色
        ChatClient.ChatClientRequestSpec chatClientRequestSpec = client.prompt().system(CommentsPrompt.SYSTEM_AI_ROLE_PROMPT);
        //新建会话
        chatClientRequestSpec = chatClientRequestSpec.advisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId)
                .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100));
        //知识库
        //获取视频内容
        AiVideoResult aiVideoResult = this.getFileTaskResult(courseId, courseNodeId, videoUrl);
        chatClientRequestSpec = chatClientRequestSpec.system(CommentsPrompt.KNOWLEDGE_PROMPT.formatted(aiVideoResult.getBriefly()));
        //如果是首次提问，则需要引导用户进行提问
        if (StrUtil.isNotBlank(question)) {
            chatClientRequestSpec = chatClientRequestSpec.system(CommentsPrompt.GUIDED_QUESTIONING_PROMPT)
                    .system(CommentsPrompt.QUESTION_TEMPLATE.formatted(question));
        }
        return chatClientRequestSpec
                .advisors(new MessageChatMemoryAdvisor(aiChatMemoryService))
                .user(message)
                .stream().content();
    }


    @Log(ignore = true)
    @Operation(description = "文件任务", summary = "文件任务")
    @GetMapping("{courseId}/aiVideo")
    public AiVideoResult getFileTaskResult(@PathVariable Long courseId,
                                           @RequestParam long courseNodeId,
                                           @RequestParam(required = false) String videoUrl) throws Exception {
        DistributeNodeInfo distributeNodeInfo = distributeNodeInfoService.getDistributeNodeInfoInCode(LoginHelper.getUserId(),
                List.of(DistributeSaleRoleEnum.ROLE_MKMG, DistributeSaleRoleEnum.ROLE_DSPD, DistributeSaleRoleEnum.ROLE_SLMB));
        if (StrUtil.isEmpty(videoUrl)) {
            return new AiVideoResult();
        }
        if (distributeNodeInfo != null) {
            AiVideoResult aiVideoResult = videoService.getTaskResult(videoUrl);
            CheckUtils.throwIfNull(aiVideoResult, "视频正在解析中，稍后尝试！");
            return videoService.getTaskResult(videoUrl);
        }
        List<MyCourse> myCourses = myCourseAppService.getMyCourseKnowledgeList(LoginHelper.getUserId(), courseId);
        CheckUtils.throwIfNull(myCourses, "尚未解锁课节！");
        CheckUtils.throwIf(myCourses.stream()
                .noneMatch(myCourse -> myCourse.getKnowledgeNodeId().equals(courseNodeId)), "尚未解锁课节！");
        AiVideoResult aiVideoResult = videoService.getTaskResult(videoUrl);
        CheckUtils.throwIfNull(aiVideoResult, "视频正在解析中，稍后尝试！");
        return videoService.getTaskResult(videoUrl);
    }
}
